/*
 * MapUnit.hpp
 *
 *  Created on: 2013-1-13
 *      Author: heqiu
 */

#ifndef MAPUNIT_HPP_
#define MAPUNIT_HPP_

#include "ScaleUnit.hpp"
#include "MyPoint.hpp"
#include "BuildingUnit.hpp"

class MapUnit {
public:
	MapUnit() {
		m_pScaleUnit = NULL;
		m_uiShort = 0;
		m_uiLong = 0;
		m_pBuilding = NULL;
	}
	~MapUnit() {
		if (m_pBuilding != NULL) {
			delete[] m_pBuilding;
		}
	}
	int32_t init(ScaleUnit * pScaleUnit, uint32_t uiShort, uint32_t uiLong) {
		m_pScaleUnit = pScaleUnit;
		m_uiShort = uiShort;
		m_uiLong = uiLong;
		if (m_uiShort >= m_uiLong) {
			return -1;
		}
		if (m_uiLong > pScaleUnit->m_uiLength) {
			return -2;
		}
		if ((uiLong - uiShort) % 2 != 0) {
			return -3;
		}
		getPoints(m_pA, m_pB, m_pC, m_pD);
		m_pBuilding = new uint32_t[(m_uiLong + 1) * (m_uiLong + 1)];
		for (uint32_t ui = 0; ui < (m_uiLong + 1) * (m_uiLong + 1); ui++) {
			m_pBuilding[ui] = 0;
		}
		return 0;
	}
	bool bPointIn(MyPoint & p) {
		if (m_pA.m_x > m_pC.m_x) {
			if (p.m_x >= m_pD.m_x && p.m_x < m_pC.m_x) {
				if (p.m_y >= m_pD.m_y - p.m_x && p.m_y <= m_pD.m_y + p.m_x) {
					return true;
				}
			} else if (p.m_x >= m_pC.m_x && p.m_x < m_pA.m_x) {
				if (p.m_y >= m_pD.m_y - p.m_x && p.m_y <= m_uiLong - p.m_x) {
					return true;
				}
			} else if (p.m_x >= m_pA.m_x && p.m_x <= m_pB.m_x) {
				if (p.m_y >= p.m_x - m_pA.m_x && p.m_y <= m_uiLong - p.m_x) {
					return true;
				}
			}
		} else {
			if (p.m_x >= m_pD.m_x && p.m_x < m_pA.m_x) {
				if (p.m_y >= m_pD.m_y - p.m_x && p.m_y <= m_pD.m_y + p.m_x) {
					return true;
				}
			} else if (p.m_x >= m_pA.m_x && p.m_x < m_pC.m_x) {
				if (p.m_y >= p.m_x - m_pD.m_y && p.m_y <= p.m_x + m_pD.m_y) {
					return true;
				}
			} else if (p.m_x >= m_pC.m_x && p.m_x <= m_pB.m_x) {
				if (p.m_y >= p.m_x - m_pA.m_x && p.m_y <= m_uiLong - p.m_x) {
					return true;
				}
			}
		}
		return false;
	}
	void getPoints(MyPoint & pA, MyPoint & pB, MyPoint & pC, MyPoint & pD) {
		pA.m_x = m_uiShort;
		pA.m_y = 0;
		pB.m_x = m_uiShort + (m_uiLong - m_uiShort) / 2;
		pB.m_y = (m_uiLong - m_uiShort) / 2;
		pC.m_x = (m_uiLong - m_uiShort) / 2;
		pC.m_y = m_uiShort + (m_uiLong - m_uiShort) / 2;
		pD.m_x = 0;
		pD.m_y = m_uiShort;
	}

	void cycle(void (*func)(uint32_t, uint32_t)) {
		//func(123,321);
		uint32_t uiBegin = 0;
		for (uint32_t uiLen = m_uiShort; uiLen <= m_uiLong; uiLen++) {
			for (uint32_t ui = (uiBegin + 1) / 2; ui <= m_uiShort + uiBegin / 2;
					ui++) {
				uint32_t ui2 = uiLen - ui;
				func(ui, ui2);
			}
			uiBegin++;
		}
	}

	void getWinPoint(MyPoint pMap, MyPoint & pWin) {
		pWin.m_x = (pMap.m_x - pMap.m_y + m_uiShort);
		pWin.m_y = (pMap.m_x + pMap.m_y - m_uiShort) * 2;
	}

	//获取坐标位置建筑
	uint32_t getBuilding(uint32_t uiX, uint32_t uiY) {
		uint32_t uiPos = uiX * (m_uiLong + 1) + uiY;
		return m_pBuilding[uiPos];
	}
	//检测是否可以建筑
	bool testBuilding(BuildingUnit & stNode) {
		for (uint32_t ui = 0; ui < stNode.m_xLen; ui++) {
			for (uint32_t uj = 0; uj < stNode.m_yLen; uj++) {
				MyPoint stPoint(stNode.m_pPos.m_x + ui, stNode.m_pPos.m_y + uj);
				if (!bPointIn(stPoint)) {
					return false;
				}
				//已经有建筑
				if (getBuilding(stPoint.m_x, stPoint.m_y) > 0) {
					return false;
				}
			}
		}
		return true;
	}
	//在地图上建筑
	bool setBuilding(BuildingUnit & stNode) {
		if (testBuilding(stNode)) {
			for (uint32_t ui = 0; ui < stNode.m_xLen; ui++) {
				for (uint32_t uj = 0; uj < stNode.m_yLen; uj++) {
					uint32_t uiX = stNode.m_pPos.m_x + ui;
					uint32_t uiY = stNode.m_pPos.m_y + uj;
					uint32_t uiPos = uiX * (m_uiLong + 1) + uiY;
					m_pBuilding[uiPos] = stNode.m_iId;
				}
			}
			return true;
		}
		return false;
	}

	bool testSetWay(uint32_t uiX, uint32_t uiY) {
		MyPoint stPoint(uiX, uiY);
		if (!bPointIn(stPoint)) {
			return false;
		}
		//已经有建筑
		if (getBuilding(stPoint.m_x, stPoint.m_y) > 0) {
			return false;
		}
		return true;
	}
	bool setWay(uint32_t uiX, uint32_t uiY, WayType uiWayType) {
		if (testSetWay(uiX, uiY)) {
			uint32_t uiPos = uiX * (m_uiLong + 1) + uiY;
			m_pBuilding[uiPos] = uiWayType;
			return true;
		}
		return false;
	}

	ScaleUnit * m_pScaleUnit;
	uint32_t m_uiShort;
	uint32_t m_uiLong;
	MyPoint m_pA;
	MyPoint m_pB;
	MyPoint m_pC;
	MyPoint m_pD;
	uint32_t * m_pBuilding;
};

#endif
